package ru.codegen.interfacebuilder;

import java.lang.reflect.Method;

/**
 *  Генерирует исходный код интерфейсов для классов.
 *
 * @author Roman Velichkin <vrnroman@gmail.com>
 */
public class InterfaceBuilder {

    /**
     * Получить строку, являющую собой исходный код интерфейса,
     * подходящего для класса-параметра.
     * 
     * @param clazz
     * @return
     */
    public static String getInterfaceForClass(Class<?> clazz) {
        StringBuilder builder = new StringBuilder();

        builder.append(clazz.getPackage()).append(";\n\n");

        builder.append("public interface I")
                .append(clazz.getSimpleName())
                .append(" {\n\n");


        Method[] methods=clazz.getMethods();
        for (Method method : methods) {
            if (!isMethodInObjectClass(method)) {
                addMethodToInterface(builder, method);
            }

        }
        builder.append("}");
        return builder.toString();

    }

    /**
     * Присутствует ли данный метод у Object.class.
     *
     * @param m
     * @return
     */
    private static boolean isMethodInObjectClass(Method m) {
        Method[] methods = Object.class.getMethods();
        for (Method method : methods) {
            if (m.getName().equals(method.getName())) {
                return true;
            }
        }
        return false;
    }

    /**
     * Добавить метод к строке-результату.
     * Перед методом ставится символ табуляции.
     * После метода 2 перевода строки.
     *
     * @param builder
     * @param method
     */
    private static void addMethodToInterface(StringBuilder builder, Method method) {
        builder.append("\tpublic ")
                .append(method.getReturnType().getCanonicalName())
                .append(" ")
                .append(method.getName())
                .append("(");
        Class[] paramTypes = method.getParameterTypes();
        int paramNumber = 0;
        for (Class paramClass : paramTypes) {
            if (paramNumber > 0) {
                builder.append(", ");
            }
            builder.append(paramClass.getCanonicalName())
                    .append(" ")
                    .append("param")
                    .append(paramNumber);
            ++paramNumber;
        }
        builder.append(");\n\n");
    }

}
